/**
 * @author 李桥
 * @date 2018/12/14
 * @Description: 组件详细信息构建类
 */
import Utils from '@/components/bim/componentDetailInformation/js/Utils';
import make from '@/components/bim/componentDetailInformation/js/MakeRequest';
require("./css/metaDataRender.css");

class Row{
    constructor(args){
        var self = this;
        this.args = args;
        this.num_names = 0;
        this.num_values = 0;
    }
    setName(name){
        if (this.num_names++ > 0) {
            this.args.name.html(" ");
        }
        this.args.name.html(name);
    }

    setValue(value){
        if (this.num_values++ > 0) {
            this.args.value.html(", ");
        }
        this.args.value.html(value);
    }
}

class Section{
    constructor(args){
        var self = this;
        this.domNode = args.domNode;
        this.caption = $("<caption></caption>");
        this.table = $("<table></table>");
        //初始化
        this.init();
    }

    init(){
        var tableContainer = $("<div></div>");
        var tr = $("<tr></tr>");
        var nameth = $("<th></th>");
        var valueth = $("<th></th>");

        this.table.append(this.caption);
        this.table.append(tr);
        nameth.html("属性");
        valueth.html("值");
        tr.append(nameth);
        tr.append(valueth);

        tableContainer.addClass("prop-table_container")
        tableContainer.append(this.table);
        this.domNode.append(tableContainer);
    }

    setName(name) {
        this.caption.html(name);
    }

    addRow() {
        var tr = $("<tr></tr>");
        this.table.append(tr);
        var nametd = $("<td></td>");
        var valuetd = $("<td></td>");
        tr.append(nametd);
        tr.append(valuetd);
        return new Row({name:nametd, value:valuetd});
    }
}

class MetaDataRenderer {
    constructor(args){
        var self = this;
        this.models = {};
        this.domNode = $("#"+args['domNode']);
        this.setSelected([]);
    }

    addModel(args) {
        var self = this;
        return new Promise(function (resolve, reject) {
            if (args.model) {
                self.models[args.id] = args.model;
                resolve(args.model);
            } else {
                self._loadModelFromSource(args.src).then(function(m) {
                    self.models[args.id] = m;
                    resolve(m);
                });
            }
        });
    };

    setSelected(oid) {
        var self = this;
        if (oid.length !== 1) {
            this.domNode.html("<div class='warn-info'>当前无选中构建，请选中一个构建查看构建的属性!</div>");
            return;
        };

        this.domNode.html("");

        oid = oid[0];

        if (oid.indexOf(':') !== -1) {
            oid = oid.split(':');
            var model = this.models[oid[0]].model || models[oid[0]].apiModel;
            var o = model.objects[oid[1]];

            this._renderAttributes(o);

            o.getIsDefinedBy(function(isDefinedBy){
                if (isDefinedBy.getType() == "IfcRelDefinesByProperties") {
                    isDefinedBy.getRelatingPropertyDefinition(function(pset){
                        if (pset.getType() == "IfcPropertySet") {
                            self._renderPSet(pset);
                        }
                    });
                }
            });
        } else {
            var o = this.models["1"].model.objects[oid];
            this._renderAttributes(o);
            o.properties.forEach(function(pset) {
                self._renderPSet(pset);
            });
        }
    };

    _renderAttributes(elem) {
        var s = new Section({domNode:this.domNode});
        s.setName(elem.type || elem.getType());
        ["GlobalId", "Name", "OverallWidth", "OverallHeight", "Tag"].forEach(function(k) {
            var v = elem[k];
            if (typeof(v) === 'undefined') {
                var fn = elem["get"+k];
                if (fn) {
                    v = fn.apply(elem);
                }
            }
            if (typeof(v) !== 'undefined') {
                var r = s.addRow();
                r.setName(k);
                r.setValue(v);
            }
        });
        return s;
    };

    _renderPSet(pset) {
        var s = new Section({domNode:this.domNode});
        if (pset.name && pset.children) {
            s.setName(pset.name);
            pset.children.forEach(function(v) {
                var r = s.addRow();
                r.setName(v.name);
                r.setValue(v.NominalValue);
            });
        } else {
            pset.getName(function(name) {
                s.setName(name);
            });
            var render = function(prop, index, row) {
                var r = row || s.addRow();
                prop.getName(function(name) {
                    r.setName(name);
                });
                if (prop.getNominalValue) {
                    prop.getNominalValue(function(value) {
                        r.setValue(value._v);
                    });
                }
                if (prop.getHasProperties) {
                    prop.getHasProperties(function(prop, index) {
                        render(prop, index, r);
                    });
                }
            };
            pset.getHasProperties(render);
        }
        return s;
    };

    /**
     * 加载xml数据
     * @param src
     * @private
     */
    _loadModelFromSource(src){
        return new Promise(function (resolve, reject) {
            make({url: src}).then(function(xml) {
                var json = Utils.xmlToJson(xml, {'Name': 'name', 'id': 'guid'});

                var psets = Utils.findNodeOfType(json, "properties")[0];
                var project = Utils.findNodeOfType(json, "decomposition")[0].children[0];
                var types = Utils.findNodeOfType(json, "types")[0];

                var objects = {};
                var typeObjects = {};
                var properties = {};
                psets.children.forEach(function(pset) {
                    properties[pset.guid] = pset;
                });

                var visitObject = function(parent, node) {
                    var props = [];
                    var o = (parent && parent.ObjectPlacement) ? objects : typeObjects;

                    if (node["xlink:href"]) {
                        if (!o[parent.guid]) {
                            var p = Utils.clone(parent);
                            p.GlobalId = p.guid;
                            o[p.guid] = p;
                            o[p.guid].properties = []
                        }
                        var g = node["xlink:href"].substr(1);
                        var p = properties[g];
                        if (p) {
                            o[parent.guid].properties.push(p);
                        } else if (typeObjects[g]) {
                            // If not a pset, it is a type, so concatenate type props
                            o[parent.guid].properties = o[parent.guid].properties.concat(typeObjects[g].properties);
                        }
                    }
                    node.children.forEach(function(n) {
                        visitObject(node, n);
                    });
                };

                visitObject(null, types);
                visitObject(null, project);

                resolve({model: {objects: objects, source: 'XML'}});
            });
        });
    }
}

export default MetaDataRenderer